#include "MelodyCandidateFactory.h"
#include "RandomNumberGenerator.h"
#include "QDebug"
#include "Algorithms/MelodyCandidate.h"

MelodyCandidateFactory::MelodyCandidateFactory()
{
}

std::vector<Candidate*> MelodyCandidateFactory::generateInitialPopulation(int populationSize, int genomeSize) {
    std::vector<Candidate*> candidates;
    for(int i=0; i<populationSize; i++) {
        candidates.push_back(new MelodyCandidate(genomeSize,0));
        //Choose how many notes
        int notes = RandomNumberGenerator::nextInt(genomeSize -6)+6;
        for(int i2=0;i2<notes;i2++) {
            createRhythms(candidates.at(i),notes);
            createPitches(candidates.at(i),notes);
            createAmps(candidates.at(i),notes);
            createLengths(candidates.at(i),notes);
            createArg1(candidates.at(i),notes);
            createArg2(candidates.at(i),notes);
        }
        //candidates.at(i)->printGenome();
    }
    return candidates;
}

void MelodyCandidateFactory::createRhythms(Candidate* candidate, int notes) {
    //for(int i2=0; i2<notes; i2++) {
        float val = (float)RandomNumberGenerator::nextInt(8);
        candidate->addChromosome(val);
    //}
}
void MelodyCandidateFactory::createPitches(Candidate* candidate, int notes) {
    //for(int i2=0; i2<notes; i2++) {
        float val = (float)RandomNumberGenerator::nextInt(50)+45;
        candidate->addChromosome(val);
    //}
}
void MelodyCandidateFactory::createAmps(Candidate* candidate, int notes) {
    //for(int i2=0; i2<notes; i2++) {
        float val = (float)RandomNumberGenerator::nextInt(999);
        candidate->addChromosome(val);
    //}
}
void MelodyCandidateFactory::createLengths(Candidate* candidate, int notes) {
    //for(int i2=0; i2<notes; i2++) {
        float val = (float)RandomNumberGenerator::nextInt(999);
        candidate->addChromosome(val);
    //}
}
void MelodyCandidateFactory::createArg1(Candidate* candidate, int notes) {
    //for(int i2=0; i2<notes; i2++) {
        float val = (float)RandomNumberGenerator::nextInt(999);
        candidate->addChromosome(val);
    //}
}
void MelodyCandidateFactory::createArg2(Candidate* candidate, int notes) {
    //for(int i2=0; i2<notes; i2++) {
        float val = (float)RandomNumberGenerator::nextInt(999);
        candidate->addChromosome(val);
    //}
}

void MelodyCandidateFactory::resetPopulation(std::vector<Candidate*> population,int genomeSize) {
    for(int i=0; i<population.size(); i++) {
        for(int i2=0; i2<genomeSize; i2++) {
            float val = (float)RandomNumberGenerator::nextFloat(2);
            population.at(i)->setChromosome(i2,val);
        }
    }
}

std::vector<Candidate*> MelodyCandidateFactory::generateInitialPopulation(int populationSize,int genomeSize,std::vector<Candidate*> seedCandidates) {
    std::vector<Candidate*> candidates;
    //((Candidate*)genomeSize = seedCandidates.at(0))->g
    for(int i=0; i<populationSize; i++) {
        candidates.push_back(new MelodyCandidate(genomeSize,0));
        int notes = RandomNumberGenerator::nextInt(genomeSize -6)+6;
        for(int i2=0;i2<(notes*6);i2++) {
            candidates.at(i)->addChromosome(
                    ((Candidate*)seedCandidates.at(i%(seedCandidates.size())))->getChromosome(
                        i2%(
                                ((Candidate*)seedCandidates.at(i%seedCandidates.size()))->getGenome().size())
                    )
            );
        }
        ((Candidate*)candidates.at(i))->mutate(1,1);
    }
    return candidates;
}

std::vector<Candidate*> MelodyCandidateFactory::generateVariation(int populationSize, int genomeSize, Candidate *seedCandidate) {
    std::vector<Candidate*> candidates;
    //((Candidate*)genomeSize = seedCandidates.at(0))->g
    for(int i=0; i<populationSize; i++) {
        candidates.push_back(new MelodyCandidate(genomeSize,0));
        candidates.at(i)->clone(seedCandidate);
        //int notes = RandomNumberGenerator::nextInt(genomeSize -6)+6;
        //for(int i2=0;i2<(notes*6);i2++) {
        //    candidates.at(i)->addChromosome(
        //            ((Candidate*)seedCandidates.at(i%(seedCandidates.size())))->getChromosome(
        //                i2%(
        //                        ((Candidate*)seedCandidates.at(i%seedCandidates.size()))->getGenome().size())
        //            )
        //    );
        //}
        //((Candidate*)candidates.at(i))->mutate(1,1);
        candidates.at(i)->variation();
        //candidates.at(i)->variation();
    }
    return candidates;
}
